package com.zl.gmadmin.configuration;

import com.zl.gmadmin.common.ApiResponse;
import com.zl.gmadmin.common.Status;
import com.zl.gmadmin.exception.BaseException;
import com.zl.gmadmin.exception.SecurityException;
import com.zl.gmadmin.exception.UserException;
import com.zl.gmadmin.utils.LogUtil;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import javax.xml.bind.ValidationException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangliang
 * @version 1.0
 * @date 2021/2/7 12:56
 * 全局controller异常处理
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理所有不可知的异常
     */
    @ExceptionHandler(Throwable.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handleException(Throwable e){
        // 打印堆栈信息
        LogUtil.error(getStackTrace(e));
        LogUtil.debug("运行不可知得异常");
        return buildResponseEntity(new BaseException(e.getMessage()));
    }

    @ExceptionHandler(BaseException.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handleException(BaseException e){
        // 打印堆栈信息
        LogUtil.error("运行时异常:"+getStackTrace(e));
        return buildResponseEntity(e);
    }
    /**
     * 处理自定义user异常
     * @param e
     * @return
     */
    @ExceptionHandler(UserException.class)
    public ResponseEntity<ApiResponse> userException(UserException e){
        LogUtil.error("用户异常返回");
        return buildResponseEntity(e);
    }

    /**
     * 处理自定security异常
     * @param e
     * @return
     */
    @ExceptionHandler(SecurityException.class)
    public ResponseEntity<ApiResponse> baseException(SecurityException e){
        LogUtil.error("安全验证异常");
        return buildResponseEntity(e);
    }

    /**
     * 统一返回异常
     */
    private ResponseEntity<ApiResponse> buildResponseEntity(BaseException e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ApiResponse.ofException(e));
    }

    /**
     * 获取堆栈信息
     */
    public static String getStackTrace(Throwable throwable){
        StringWriter sw = new StringWriter();
        try (PrintWriter pw = new PrintWriter(sw)) {
            throwable.printStackTrace(pw);
            return sw.toString();
        }
    }




    // 参数校验异常处理 ===========================================================================
    // MethodArgumentNotValidException是springBoot中进行绑定参数校验时的异常,需要在springBoot中处理,其他需要处理ConstraintViolationException异常进行处理.



    /**
     * 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        LogUtil.error("方法参数校验:{}", e.getMessage());
        return buildResponseEntity(new BaseException(e.getBindingResult().getFieldError().getDefaultMessage()));
    }

    /**
     * ValidationException
     */
    @ExceptionHandler(javax.xml.bind.ValidationException.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handleValidationException(ValidationException e) {
        LogUtil.error("ValidationException:", e);
        return buildResponseEntity(new BaseException(e.getCause().getMessage()));
    }

    /**
     * ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handleConstraintViolationException(ConstraintViolationException e) {
        LogUtil.error("ValidationException:" + e.getMessage(), e);
        return buildResponseEntity(new BaseException(e.getMessage()));
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handlerNoFoundException(NoHandlerFoundException e) {
        return buildResponseEntity(new BaseException(Status.HANDLER_NOFOUND));
    }


    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseBody
    public ResponseEntity<ApiResponse> handleDuplicateKeyException(DuplicateKeyException e) {
        String message=e.getCause().getMessage();
        message=setMessage(message);

//        String column="";
//
//        if (e.getCause().getMessage().contains("sys_role.uniq_name")){
//             column="角色名称";
//            int index1=message.indexOf("'");
//            //根据第一个点的位置 获得第二个'的位置
//            int index2=message.indexOf("'", index1+1);
//            column=column+message.substring(index1,index2+1);
//
//        }else if (e.getCause().getMessage().contains("sys_user.username")
//        ){
//             column="用户名";
//            int index1=message.indexOf("'");
//            //根据第一个点的位置 获得第二个'的位置
//            int index2=message.indexOf("'", index1+1);
//            column=column+message.substring(index1,index2+1);
//        }else if (message.contains("sys_user.UK_kpubos9gc2cvtkb0thktkbkes")){
//            column="邮箱";
//            int index1=message.indexOf("'");
//            //根据第一个点的位置 获得第二个'的位置
//            int index2=message.indexOf("'", index1+1);
//            column=column+message.substring(index1,index2+1);
//        }else if (message.contains("sys_menu.uniq_name")){
//            column="菜单名称";
//            int index1=message.indexOf("'");
//            //根据第一个点的位置 获得第二个'的位置
//            int index2=message.indexOf("'", index1+1);
//            column=column+message.substring(index1,index2+1);
//        }else if (message.contains("sys_menu.uniq_title")){
//            column="菜单标题";
//            int index1=message.indexOf("'");
//            //根据第一个点的位置 获得第二个'的位置
//            int index2=message.indexOf("'", index1+1);
//            column=column+message.substring(index1,index2+1);
//        }
        return buildResponseEntity(new BaseException(5009,"'"+message+"'参数值已存在，请重新输入",null));
    }

    /**
     * 根据异常字段名称设置返回消息
     * @param message
     * @return
     */
    String setMessage(String message){
        // 不能重复的属性
        String[] duplicateField={"sys_role.uniq_name","sys_user.username","sys_user.UK_kpubos9gc2cvtkb0thktkbkes"
        ,"sys_menu.uniq_name","sys_menu.uniq_title","sys_dict.sys_dict_name_uindex"};
        Map<String,String> duplicateFieldMap=new HashMap<>();
        duplicateFieldMap.put("sys_role.uniq_name","角色名");
        duplicateFieldMap.put("sys_user.username","用户名");
        duplicateFieldMap.put("sys_user.UK_kpubos9gc2cvtkb0thktkbkes","用户邮箱");
        duplicateFieldMap.put("sys_menu.uniq_name","菜单名");
        duplicateFieldMap.put("sys_menu.uniq_title","菜单标题");
        duplicateFieldMap.put("sys_dict.sys_dict_name_uindex","字典名称");

        String column="";

        for (String field:duplicateField
             ) {
             if (message.contains(field)){
                 column=duplicateFieldMap.get(field);
             }
        }
//            int index1=message.indexOf("'");
//            //根据第一个点的位置 获得第二个'的位置
//            int index2=message.indexOf("'", index1+1);
//            column=column+message.substring(index1,index2+1);

            return column;
    }
}
